package cn.chen.miaosha.controller;

import cn.chen.miaosha.domain.Goods;
import cn.chen.miaosha.domain.MiaoshaOrder;
import cn.chen.miaosha.domain.MiaoshaUser;
import cn.chen.miaosha.domain.OrderInfo;
import cn.chen.miaosha.rabbitmq.MQSender;
import cn.chen.miaosha.rabbitmq.MiaoshaMsg;
import cn.chen.miaosha.redis.GoodsKey;
import cn.chen.miaosha.redis.MiaoshaKey;
import cn.chen.miaosha.redis.RedisService;
import cn.chen.miaosha.result.CodeMsg;
import cn.chen.miaosha.result.Result;
import cn.chen.miaosha.service.GoodsService;
import cn.chen.miaosha.service.MiaoshaService;
import cn.chen.miaosha.service.OrderService;
import cn.chen.miaosha.util.MD5Util;
import cn.chen.miaosha.util.UUIDUtil;
import cn.chen.miaosha.vo.GoodsVO;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.UUID;

@Controller
@RequestMapping("/miaosha")
public class MiaoshaController implements InitializingBean{

    @Autowired
    GoodsService goodsService;

    @Autowired
    OrderService orderService;

    @Autowired
    MiaoshaService miaoshaService;

    @Autowired
    RedisService redisService;

    @Autowired
    MQSender sender;

    private HashMap<Long, Boolean> localOverMap = new HashMap<Long, Boolean>();

    /**
     * QPS:764.8488531064864
     * 5000 * 10
     * @param model
     * @param user
     * @param goodsId
     * @return
     */
    @RequestMapping("/do_miaosha2")
    public String doMiaosha2(Model model, MiaoshaUser user,
                            @RequestParam("goodsId")Long goodsId){
        model.addAttribute("user",user);

        if(user == null){
            return "login";
        }

        GoodsVO goods = goodsService.getGoodsVOById(goodsId);
        int stock = goods.getStockCount();
        //判断库存
        if(stock <= 0){
            model.addAttribute("errorMsg", CodeMsg.MIAOSHA_OVER.getMsg());
            return "miaosha_fail";
        }
        //判断是否已经秒杀到了
        MiaoshaOrder order = orderService.getMiaoshaOrderByUserIdGoodsId(user.getId(), goods.getId());
        if(order != null){
            model.addAttribute("errorMsg", CodeMsg.REPEATE_MIAOSHA.getMsg());
            return "miaosha_fail";
        }
        //减少库存 下订单 写入秒杀订单
        OrderInfo orderInfo = miaoshaService.miaosha(user, goods);
        model.addAttribute("orderInfo", orderInfo);
        model.addAttribute("goods", goods);
        return "order_detail";
    }

    /**
     * 系统初始化, 库存缓存到Redis
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        List<GoodsVO> goodslist = goodsService.listGoodsVO();
        if(goodslist == null){
            return;
        }
        for(Goods goods : goodslist){
            redisService.set(GoodsKey.getMiaoshaGoodsStock,""+goods.getId(),goods.getGoodsStock());
            localOverMap.put(goods.getId(), false);
        }
    }

    @RequestMapping(value = "/do_miaosha", method = RequestMethod.POST)
    @ResponseBody
    public Result<Integer> doMiaosha(Model model, MiaoshaUser user,
                                     @RequestParam("goodsId")Long goodsId,
                                     @PathVariable("path") String path){
        model.addAttribute("user",user);

        if(user == null){
            return Result.error(CodeMsg.SESSION_ERROR);
        }

        //验证path
        boolean checkPath = miaoshaService.checkPath(user, goodsId, path);
        if(!checkPath){
            return Result.error(CodeMsg.REQUEST_ILLEGAL);
        }

        // 内存标记，减少Redis访问
        boolean over = localOverMap.get(goodsId);
        if(over){
            return Result.error(CodeMsg.MIAOSHA_OVER);
        }

        //减库存
        long stock = redisService.dec(GoodsKey.getMiaoshaGoodsStock,""+goodsId);
        if(stock < 0){
            localOverMap.put(goodsId, true);
            return Result.error(CodeMsg.MIAOSHA_OVER);
        }
        //判断是否已经秒杀到了
        MiaoshaOrder order = orderService.getMiaoshaOrderByUserIdGoodsId(user.getId(), goodsId);
        if(order != null){
            return Result.error(CodeMsg.REPEATE_MIAOSHA);
        }
        //入队
        MiaoshaMsg mm = new MiaoshaMsg();
        mm.setUser(user);
        mm.setGoodsId(goodsId);
        sender.sendMiaoshaMessage(mm);

        return Result.success(0);

        /**
        GoodsVO goods = goodsService.getGoodsVOById(goodsId);
        int stock = goods.getStockCount();
        //判断库存
        if(stock <= 0){
            return Result.error(CodeMsg.MIAOSHA_OVER);
        }
        //判断是否已经秒杀到了
        MiaoshaOrder order = orderService.getMiaoshaOrderByUserIdGoodsId(user.getId(), goods.getId());
        if(order != null){
            return Result.error(CodeMsg.REPEATE_MIAOSHA);
        }
        //减少库存 下订单 写入秒杀订单
        OrderInfo orderInfo = miaoshaService.miaosha(user, goods);
        return Result.success(orderInfo);
         */
    }

    /**
     * orderId：成功
     * -1：秒杀失败
     * 0：排队中
     * @param model
     * @param user
     * @param goodsId
     * @return
     */
    @RequestMapping(value = "/result", method = RequestMethod.GET)
    @ResponseBody
    public Result<Long> getMiaoshaResult(Model model, MiaoshaUser user,
                                     @RequestParam("goodsId")Long goodsId){
        model.addAttribute("user",user);

        if(user == null){
            return Result.error(CodeMsg.SESSION_ERROR);
        }

        long result = miaoshaService.getMiaoshaResult(user.getId(), goodsId);
        return Result.success(result);
    }

    @RequestMapping(value = "/path", method = RequestMethod.GET)
    @ResponseBody
    public Result<String> getMiaoshaPath(Model model, MiaoshaUser user,
                                     @RequestParam("goodsId")Long goodsId){
        model.addAttribute("user",user);

        if(user == null){
            return Result.error(CodeMsg.SESSION_ERROR);
        }
        String path = miaoshaService.createMiaoshaPath(user, goodsId);
        return Result.success(path);
    }

}
